Skip to content

[PET-40] Replace eslint and prettier with biome (Migrate to Biome and standardize TypeScript imports)#41

Merged
zigcccc merged 6 commits intomainfrom
PET-40-replace-eslint-and-prettier-with-biome
Mar 19, 2026
Merged

[PET-40] Replace eslint and prettier with biome (Migrate to Biome and standardize TypeScript imports)#41
zigcccc merged 6 commits intomainfrom
PET-40-replace-eslint-and-prettier-with-biome

Conversation

@zigcccc
Copy link
Owner

@zigcccc zigcccc commented Mar 19, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Improved null-safety in push-notification enabling logic.
  • Refactor

    • Standardized TypeScript import usage and simplified the radio-input context contract.
  • Style

    • Switched repository formatting/linting to Biome and consolidated formatting rules.
  • Tests

    • Reformatted many table-driven tests for consistent, more readable style.
  • Documentation

    • Updated developer guidance and scripts to reflect Biome usage.
  • Chores

    • Updated npm scripts and dev tooling dependencies accordingly.

@zigcccc zigcccc self-assigned this Mar 19, 2026
@zigcccc zigcccc added enhancement New feature or request dependencies labels Mar 19, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

Caution

Review failed

Pull request was closed or merged during review

Walkthrough

Replace Prettier/ESLint with Biome tooling, standardize many TypeScript imports to import type, reformat Jest parameterized tests, apply small modernizations (optional chaining, Object.hasOwn, **), switch Node built-ins to node: specifiers in seeders, and remove Prettier/ESLint configs.

Changes

Cohort / File(s) Summary
Tooling & config
biome.json, .zed/settings.json, package.json, prettier.config.js, eslint.config.js, .prettierignore, CLAUDE.md, babel.config.cjs
Remove Prettier/ESLint configs, add Biome config and editor settings, update npm scripts/lint-staged to Biome, adjust docs, and minor babel export style change.
Bulk type-only import updates
convex/..., src/** (many files, e.g. src/components/**, src/hooks/**, src/context/**, src/tests/fixtures/*, src/utils/*)
Convert numerous import { type X } to import type { X } (erase at runtime) and reorder some imports for consistency.
Tests — formatting & import order
src/__tests__/*, src/components/**/*/*.test.tsx, src/hooks/*/*test.ts, src/utils/notifications.test.ts
Reformat many it.each parameterized tests to a more compact callback style and adjust import ordering; no test logic changes.
Component & UI tweaks
src/components/**, src/app/**, src/context/**, src/components/ui/RadioInput/*
Reorder imports/JSX prop positions, add // biome-ignore suppressions for array-index keys, memoize RadioInput change handler and adjust RadioInput context types (string-based).
Node built-ins & seeders
db/seeders/dictionaryEntries/getDictionaryWords.js, db/seeders/dictionaryEntries/getDictionaryWordsExplanations.js
Switch to node:-prefixed built-in module specifiers and minor string/template literal modernizations.
Small logic modernizations
src/utils/clone.ts, src/utils/words.ts, src/hooks/usePushNotifications/usePushNotifications.ts
Use Object.hasOwn, replace Math.pow with **, and make status?.hasToken null-safe; no behavioral changes intended.
Jest/mock typing tweaks
jest.setup.tsx
Adjust Octicons mock typing, allow any for uniProps with inline biome-ignore, and convert imports to type-only where appropriate.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

refactor

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed Title check skipped as CodeRabbit has written the PR title.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch PET-40-replace-eslint-and-prettier-with-biome
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai bot changed the title [PET-40] Replace eslint and prettier with biome (@coderabbitai) [PET-40] Replace eslint and prettier with biome (Migrate to Biome and standardize TypeScript imports) Mar 19, 2026
@github-actions
Copy link

github-actions bot commented Mar 19, 2026

🚀 Expo preview is ready!

  • Project → petka-app
  • Platforms → android, ios
  • Scheme → petkaapp
  • Runtime Version → 1.6
  • More info

Learn more about 𝝠 Expo Github Action

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
db/seeders/dictionaryEntries/getDictionaryWords.js (1)

85-98: ⚠️ Potential issue | 🔴 Critical

Replace forEach(async ...) with for...of loop to properly await validation before closing stream.

Line 85's async forEach callback is not awaited before writeStream.end() at line 96, which can close the stream while async validation is still running. Any writes queued after the stream ends will be lost, resulting in incomplete JSONL output.

Proposed fix
-    words.forEach(async (item) => {
+    for (const item of words) {
       const isValid = await isValidDictionaryTerm(item.word);
       if (isValid) {
         console.log(`Writing word: ${item.word} with frequency: ${item.frequency}`);
         writeStream.write(`${JSON.stringify(item)}\n`);
       } else {
         console.warn('Found illegal word: ', item.word);
       }
-    });
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@db/seeders/dictionaryEntries/getDictionaryWords.js` around lines 85 - 98, The
async callback passed to words.forEach does not get awaited, so
isValidDictionaryTerm(item.word) and subsequent writeStream.write calls may
still be running when writeStream.end() is called; replace the
words.forEach(async (item) => { ... }) with an async function using a for...of
loop (for (const item of words) { ... }) and await
isValidDictionaryTerm(item.word) and the write operations before calling
writeStream.end(), ensuring all validations and writes complete; keep references
to isValidDictionaryTerm, writeStream.write, and writeStream.end so the loop
replaces the words.forEach section.
🟡 Minor comments (12)
src/hooks/useTrainingPuzzle/useTrainingPuzzle.test.ts-6-6 (1)

6-6: ⚠️ Potential issue | 🟡 Minor

Use the repository’s import { type X } form for type-only imports.

Please switch this to the configured TS import style to keep consistency with project rules.

Proposed change
-import type { Id } from '@/convex/_generated/dataModel';
+import { type Id } from '@/convex/_generated/dataModel';

As per coding guidelines, "**/*.{ts,tsx}: Use type-only imports with import { type X } syntax".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useTrainingPuzzle/useTrainingPuzzle.test.ts` at line 6, Replace the
plain type import with the project's type-only import syntax: change the current
import of Id to use the TypeScript type-only form (import { type Id } ...) so
the test module's import of Id uses the configured "import { type X }" style;
update the import statement that references Id in useTrainingPuzzle.test to use
this type-only syntax.
src/hooks/mutations/generateUseMutationHook.ts-2-2 (1)

2-2: ⚠️ Potential issue | 🟡 Minor

Conflicts with coding guidelines: import syntax style.

Same as in generateUseQueryHook.ts, this change converts from import { type FunctionReference } to import type { FunctionReference }, which conflicts with the coding guidelines that specify: "Use type-only imports with import { type X } syntax".

Ensure consistency across the codebase by either configuring Biome to use the inline type import syntax or updating the guidelines.

As per coding guidelines: "Use type-only imports with import { type X } syntax"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/mutations/generateUseMutationHook.ts` at line 2, The import in
generateUseMutationHook.ts uses the `import type { FunctionReference } from
'convex/server'` form which conflicts with the project's guideline requiring
inline type imports; change the import to the inline type-only syntax used
elsewhere (e.g., `import { type FunctionReference } from 'convex/server'`) so it
matches generateUseQueryHook.ts and the codebase convention, and verify no other
imports in this file use `import type` so the file is consistent.
src/hooks/queries/generateUseQueryHook.ts-2-2 (1)

2-2: ⚠️ Potential issue | 🟡 Minor

Conflicts with coding guidelines: import syntax style.

The change converts from import { type FunctionReference } to import type { FunctionReference }, but the coding guidelines explicitly state: "Use type-only imports with import { type X } syntax" (inline type imports).

While both syntaxes are valid TypeScript, this creates an inconsistency between the code and documented guidelines. Consider either:

  1. Configuring Biome to use inline type imports (import { type X }) to match the guidelines
  2. Or updating the coding guidelines to reflect the new preference for import type { X }

As per coding guidelines: "Use type-only imports with import { type X } syntax"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/queries/generateUseQueryHook.ts` at line 2, The import in
generateUseQueryHook.ts uses the `import type { FunctionReference }` form which
conflicts with the project's guideline to use inline type imports; change the
import to the inline type syntax `import { type FunctionReference } from
'convex/server'` so it matches other files (or, if you prefer to adopt the
`import type` form project-wide, update the Biome/formatter config and the
coding guidelines accordingly); ensure any other occurrences of `import type {
... }` are adjusted consistently.
src/hooks/useUser/useUser.ts-6-6 (1)

6-6: ⚠️ Potential issue | 🟡 Minor

Use inline type specifiers to match repository style.

Switch to import { type X } syntax here to align with the project's required TypeScript import style.

Proposed fix
-import type { CreateUser, PatchUser } from '@/convex/users/models';
+import { type CreateUser, type PatchUser } from '@/convex/users/models';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useUser/useUser.ts` at line 6, Update the import to use inline type
specifiers to match repo style: change the import that brings in CreateUser and
PatchUser in useUser.ts so it uses the `type` keyword inline (i.e., import {
type CreateUser, type PatchUser } from '...') instead of `import type {
CreateUser, PatchUser }`, ensuring other code references to CreateUser and
PatchUser remain unchanged.
src/utils/notifications.test.ts-93-93 (1)

93-93: ⚠️ Potential issue | 🟡 Minor

Fix typo in test description.

The test description contains "requestPermissionsAsyn" which should be "requestPermissionsAsync" (missing the final 'c').

✏️ Proposed fix
-  ])('should use the status received from the requestPermissionsAsyn when status of getPermissionsAsync is %s', async (getPermissionsAsyncStatus) => {
+  ])('should use the status received from the requestPermissionsAsync when status of getPermissionsAsync is %s', async (getPermissionsAsyncStatus) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/notifications.test.ts` at line 93, The test title string in the
Jest test starting with "should use the status received from the
requestPermissionsAsyn when status of getPermissionsAsync is %s" contains a
typo; update that string to "requestPermissionsAsync" (add the missing 'c') so
the description reads "should use the status received from the
requestPermissionsAsync when status of getPermissionsAsync is %s" in the test
case that iterates over getPermissionsAsyncStatus.
src/components/navigation/GenericStackScreen/GenericStackScreen.tsx-2-2 (1)

2-2: ⚠️ Potential issue | 🟡 Minor

Use inline type modifier for PropsWithChildren import.

Replace import type { PropsWithChildren } from 'react'; with import { type PropsWithChildren } from 'react'; to align with the project's type-only import syntax preference.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/navigation/GenericStackScreen/GenericStackScreen.tsx` at line
2, Replace the type-only import syntax on GenericStackScreen by changing the
import of PropsWithChildren to use the inline type modifier; update the existing
import statement that references PropsWithChildren so it reads with "import {
type PropsWithChildren } from 'react';" (locate the import that currently says
"import type { PropsWithChildren } from 'react';" and adjust it accordingly).
src/components/elements/GuessGrid/GuessGrid.types.ts-1-1 (1)

1-1: ⚠️ Potential issue | 🟡 Minor

Use import { type X } syntax for type imports.

Change import type { CheckedLetter, PuzzleGuessAttempt } to import { type CheckedLetter, type PuzzleGuessAttempt } to align with project conventions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/elements/GuessGrid/GuessGrid.types.ts` at line 1, The import
in GuessGrid.types.ts should use the `import { type ... }` form; replace the
current `import type { CheckedLetter, PuzzleGuessAttempt }` with `import { type
CheckedLetter, type PuzzleGuessAttempt }` so both CheckedLetter and
PuzzleGuessAttempt are explicitly imported as types and follow project
conventions.
src/hooks/useDailyPuzzle/useDailyPuzzle.test.ts-6-6 (1)

6-6: ⚠️ Potential issue | 🟡 Minor

Use the configured type-import style in tests too.

Switch to import { type Id } from '@/convex/_generated/dataModel'; for guideline consistency. Per coding guidelines, type-only imports must use import { type X } syntax, not import type { X }.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useDailyPuzzle/useDailyPuzzle.test.ts` at line 6, Change the
type-only import style to match project guidelines: replace the current import
using the "import type { Id }" form with the "import { type Id } from
'@/convex/_generated/dataModel';" style in the test file (referencing the Id
type import at the top of src/hooks/useDailyPuzzle/useDailyPuzzle.test.ts) so
tests use the configured type-import syntax.
src/utils/puzzles.ts-3-3 (1)

3-3: ⚠️ Potential issue | 🟡 Minor

Use the correct type-only import syntax.

Switch to import { type Puzzle } from '@/convex/puzzles/models'; to match the project's TypeScript import convention defined in CLAUDE.md.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/puzzles.ts` at line 3, Update the import to use TypeScript's
type-only import form: replace the current default-style import of Puzzle with
an explicit type import for the Puzzle symbol from '@/convex/puzzles/models'
(i.e., use "import { type Puzzle } from '@/convex/puzzles/models';") so it
follows the project's CLAUDE.md convention and signals this is a type-only
dependency.
src/components/ui/Card/Card.tsx-2-2 (1)

2-2: ⚠️ Potential issue | 🟡 Minor

Use inline type specifiers for type-only imports.

Change to import { type PropsWithChildren, type ReactNode } from 'react'; to match the required type-import syntax.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/Card/Card.tsx` at line 2, The import uses a type-only
import statement; update the import to use inline type specifiers by changing
the import of PropsWithChildren and ReactNode to `import { type
PropsWithChildren, type ReactNode } from 'react';` so both PropsWithChildren and
ReactNode are explicitly marked as types in the import that appears at the top
of the Card component file (the existing import line that currently reads
`import type { PropsWithChildren, ReactNode } from 'react';`).
src/components/ui/TextInput/TextInput.tsx-31-31 (1)

31-31: ⚠️ Potential issue | 🟡 Minor

Place ref before other JSX props in this component.

ref should come first, then remaining props in sorted order for this codebase convention.

♻️ Suggested adjustment
-export function TextInput({ error, ref, label, style, ...rest }: Readonly<Props>) {
+export function TextInput({ error, ref, label, style, accessibilityLabel, ...rest }: Readonly<Props>) {
@@
-      <UniTextInput {...rest} accessibilityLabel={label ?? rest.placeholder} ref={ref} style={[styles.input, style]} />
+      <UniTextInput
+        ref={ref}
+        accessibilityLabel={accessibilityLabel ?? label ?? rest.placeholder}
+        style={[styles.input, style]}
+        {...rest}
+      />

Based on learnings: Applies to src/**/*.{tsx} : JSX props must have key and ref come first, remaining props in alphabetical order.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/TextInput/TextInput.tsx` at line 31, Move the ref prop to
be the first JSX prop on UniTextInput, then order the remaining explicit props
alphabetically (e.g. accessibilityLabel, style) and place the {...rest} spread
last so explicit props are not accidentally shadowed; update the UniTextInput
element in TextInput.tsx to follow that ordering.
src/components/elements/DailyPuzzleUsersPresence/DailyPuzzleUsersPresence.test.tsx-66-66 (1)

66-66: ⚠️ Potential issue | 🟡 Minor

Fix test-title placeholder key typo.

Line 66 uses $numberOfOnlinePlayers, but the table data key is numOfOnlinePlayers, so the interpolated count won’t render in test names.

Suggested patch
-  ])('should render "$expectedText" when there are $numberOfOnlinePlayers online', ({
+  ])('should render "$expectedText" when there are $numOfOnlinePlayers online', ({
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/components/elements/DailyPuzzleUsersPresence/DailyPuzzleUsersPresence.test.tsx`
at line 66, The test title uses the wrong placeholder `$numberOfOnlinePlayers`
so the interpolated count never appears; update the table-driven test title (the
string passed to the test/it call) to use the correct key `$numOfOnlinePlayers`
that matches the data in the test table (referencing the existing placeholders
`expectedText` and `numOfOnlinePlayers` in DailyPuzzleUsersPresence.test.tsx) so
test names render the online player count correctly.
🧹 Nitpick comments (7)
src/context/Prompt/Prompt.context.ts (1)

3-3: Import syntax doesn't match coding guidelines.

The change uses import type { PromptProviderProps } but the coding guidelines specify using import { type X } syntax for type-only imports.

Both syntaxes work correctly for type-only imports, but the codebase convention states: "Type-only imports must use import { type X } syntax."

Consider reverting to the inline type syntax for consistency:

Suggested change
-import type { PromptProviderProps } from './Prompt.types';
+import { type PromptProviderProps } from './Prompt.types';

As per coding guidelines: "Use type-only imports with import { type X } syntax"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/context/Prompt/Prompt.context.ts` at line 3, Replace the type-only import
to follow the codebase convention by changing the import statement that
references PromptProviderProps to use the inline type syntax (import { type
PromptProviderProps } ...) instead of import type { PromptProviderProps }, so
update the import that currently names PromptProviderProps in Prompt.context to
the { type ... } form for consistency.
src/hooks/useLeaderboards/useLeaderboards.test.ts (1)

9-9: Use the project’s inline type-import convention.

Line 9 currently uses import type { Id } ...; repository style requires import { type Id } ....

As per coding guidelines, **/*.{ts,tsx}: Use type-only imports with import { type X } syntax.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useLeaderboards/useLeaderboards.test.ts` at line 9, Replace the
type-only import to match project convention: change the existing import
statement that references Id from "import type { Id } from
'@/convex/_generated/dataModel';" to use the inline type-import style ("import {
type Id } from '@/convex/_generated/dataModel';"), ensuring the symbol Id is
imported with the "type" modifier inside the braces.
jest.setup.tsx (1)

1-2: Please switch to inline type imports for consistency with repo rules.

Lines 1-2 use import type { ... }; codebase convention expects import { type ... }.

As per coding guidelines, **/*.{ts,tsx}: Use type-only imports with import { type X } syntax.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@jest.setup.tsx` around lines 1 - 2, The imports in jest.setup.tsx use
standalone "import type" syntax; update them to inline type imports to follow
repo convention by changing the two lines importing Octicons and ComponentProps
to use "import { type Octicons } from '@expo/vector-icons'" and "import { type
ComponentProps } from 'react'"; ensure only the syntax changes (types remain
type-only) and no runtime imports are altered.
src/__tests__/settings.test.tsx (1)

6-6: Please align type imports with the repo’s inline style.

Lines 6 and 10 use import type { ... }; this codebase guideline expects import { type ... }.

As per coding guidelines, **/*.{ts,tsx}: Use type-only imports with import { type X } syntax.

Also applies to: 10-10

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/__tests__/settings.test.tsx` at line 6, Update the type-only imports to
the repo's preferred inline style: replace the `import type { ComponentProps }
from 'react'` form with the `import { type ComponentProps } from 'react'`
syntax, and do the same for the other type-only import on line 10 (replace
`import type { ... }` with `import { type ... }`) so both ComponentProps and the
second imported type use the `import { type ... }` form.
src/context/ActionSheet/ActionSheet.provider.tsx (1)

9-9: Use inline type-import syntax to match repo convention.

Line 9 uses import type { ... }, while this repo rule expects import { type ... }.

As per coding guidelines, **/*.{ts,tsx}: Use type-only imports with import { type X } syntax.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/context/ActionSheet/ActionSheet.provider.tsx` at line 9, The import uses
the non-preferred "import type { ActionSheetPressCallback }" form; update it to
the repo convention by changing the import to the inline type-import syntax
"import { type ActionSheetPressCallback } from './ActionSheet.types';" so the
ActionSheet.provider.tsx file (and specifically the ActionSheetPressCallback
import) follows the project's type-only import rule.
src/components/ui/RadioInput/RadioInput.types.ts (1)

15-18: Type safety reduction by removing generic from context.

The change from Pick<RadioInputProps<Value>, 'value' | 'onChange'> to a non-generic { onChange: (newValue: string) => void; value?: string } loses compile-time type narrowing. Consumers like settings.tsx expect onChange to receive only specific string literals (e.g., 'qwerty' | 'abcde' or 'system' | 'light' | 'dark'), but the context now accepts any string.

This is mitigated by the as Value cast in RadioInput.tsx, so runtime behavior is preserved. However, if an RadioInput.Item is added with an invalid value string, TypeScript won't catch the mismatch.

If this simplification is intentional for Biome compatibility or other reasons, consider documenting the trade-off.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/RadioInput/RadioInput.types.ts` around lines 15 - 18, The
RadioInputContextProps type lost its generic, reducing type safety; change
RadioInputContextProps back to a generic (e.g., RadioInputContextProps<Value
extends string>) and type it as Pick<RadioInputProps<Value>, 'value' |
'onChange'> or equivalently { onChange: (newValue: Value) => void; value?: Value
}, then update the RadioInput context creation and the provider usage in
RadioInput.tsx to use the same generic Value so consumers (like settings.tsx and
RadioInput.Item) get compile-time narrowing and you can remove the unsafe `as
Value` cast.
src/components/ui/RadioInput/RadioInput.tsx (1)

19-20: Unchecked type cast bridges generic to non-generic context.

The as Value cast on line 19 bypasses TypeScript's type validation. While this works at runtime when RadioInput.Item values match the expected Value union, TypeScript cannot catch mismatches like:

<RadioInput<'light' | 'dark'> onChange={handler} value="light">
  <RadioInput.Item value="invalid" label="Oops" /> {/* No compile error */}
</RadioInput>

The memoization pattern itself is correct. If preserving full type safety is important, consider keeping the generic on the context type or adding runtime validation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/RadioInput/RadioInput.tsx` around lines 19 - 20, The
unchecked cast in handleChange (newValue: string) => onChange(newValue as Value)
should be removed and the context should preserve the generic Value type so
TypeScript can validate item values; update the RadioInput context type to be
generic (e.g., RadioInputContext<Value>) and change handleChange to accept Value
(or narrow/validate the incoming value before calling onChange) so contextValue
is memoized with the correctly typed handleChange and value, ensuring
RadioInput.Item values are type-checked against the RadioInput<Value> generic
rather than bypassed by an any/string cast.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.zed/settings.json:
- Around line 34-38: Remove the unsupported Biome YAML formatter configuration:
delete or replace the "YAML" -> "formatter" -> "language_server" entry that sets
{ "name": "biome" } (the "YAML" block and its "formatter" / "language_server"
keys) and either remove the YAML formatter section entirely or point it to a
supported formatter (e.g., Prettier or yamlfmt) so the settings no longer
reference Biome for YAML formatting.

In `@convex/leaderboards/queries.ts`:
- Line 1: The import in queries.ts should follow the project's type-only import
style; replace the current "import type { NamedTableInfo, Query } from
'convex/server'" with the guideline-compliant form using explicit type markers
for each symbol (i.e., import { type NamedTableInfo, type Query } from
'convex/server') so that NamedTableInfo and Query are imported as type-only
imports.
- Line 7: The import uses the "import type { DataModel, Id }" form which
conflicts with the repo guideline; change it to the style-required type-only
syntax by using named imports with the type modifier (e.g., import { type
DataModel, type Id } from '../_generated/dataModel'), updating the import that
references DataModel and Id in convex/leaderboards/queries.ts so both symbols
are imported as type-only with the "type" modifier on each identifier.
- Line 10: The import in convex/leaderboards/queries.ts should use the project's
preferred type-only syntax; replace the current `import type { User }` with the
guideline-compliant `import { type User }` form so the User type is imported as
a type-only binding; locate the import of User at the top of the file and update
that statement accordingly.

In `@src/components/elements/GuessGrid/GuessGrid.test.tsx`:
- Line 3: Replace the current type-only import using the "import type { Id }"
form with the project-preferred "import { type Id }" syntax; update the import
statement at the top of GuessGrid.test.tsx so it reads using the named import
modifier (referencing the Id type) and ensure the file imports follow the coding
guideline "Use type-only imports with import { type X } syntax".

In `@src/components/elements/GuessGrid/GuessGrid.tsx`:
- Line 7: Revert the import to use inline type-only specifiers per the coding
guideline: change the current top-level "import type { GuessGridCellProps,
GuessGridProps }" back to the inline form "import { type GuessGridCellProps,
type GuessGridProps }" (apply the same pattern for any other files in this PR
that were converted), locating the import in GuessGrid.tsx and any other modules
that now use "import type" and replace with the "{ type X }" syntax for each
type symbol.

In `@src/tests/fixtures/leaderboards.ts`:
- Around line 1-2: The imports in leaderboards.ts should use the inline
type-only import syntax per guidelines; change the top imports so Id,
LeaderboardWithScores, and any other types are imported with the pattern import
{ type Id } and import { type LeaderboardWithScores, leaderboardType } (i.e.,
keep non-type exports like leaderboardType as normal imports and mark only types
with the inline "type" modifier) instead of converting the entire statements to
top-level "import type" declarations.

In `@src/tests/fixtures/puzzleGuessAttempts.ts`:
- Line 1: The import in puzzleGuessAttempts.ts uses the `import type { Id }`
form which conflicts with the repo guideline; change it to the preferred
type-only import syntax `import { type Id }` so the type is imported with the
`type` modifier inside the braces (update the import that references the `Id`
type accordingly).

In `@src/tests/fixtures/puzzles.ts`:
- Line 1: The import uses the banned "import type { Id }" form; change it to the
project-preferred type-only import syntax "import { type Id }" so the type Id is
imported using the named type-only form (look for the Id import in
src/tests/fixtures/puzzles.ts and replace the current import statement
accordingly).

---

Outside diff comments:
In `@db/seeders/dictionaryEntries/getDictionaryWords.js`:
- Around line 85-98: The async callback passed to words.forEach does not get
awaited, so isValidDictionaryTerm(item.word) and subsequent writeStream.write
calls may still be running when writeStream.end() is called; replace the
words.forEach(async (item) => { ... }) with an async function using a for...of
loop (for (const item of words) { ... }) and await
isValidDictionaryTerm(item.word) and the write operations before calling
writeStream.end(), ensuring all validations and writes complete; keep references
to isValidDictionaryTerm, writeStream.write, and writeStream.end so the loop
replaces the words.forEach section.

---

Minor comments:
In
`@src/components/elements/DailyPuzzleUsersPresence/DailyPuzzleUsersPresence.test.tsx`:
- Line 66: The test title uses the wrong placeholder `$numberOfOnlinePlayers` so
the interpolated count never appears; update the table-driven test title (the
string passed to the test/it call) to use the correct key `$numOfOnlinePlayers`
that matches the data in the test table (referencing the existing placeholders
`expectedText` and `numOfOnlinePlayers` in DailyPuzzleUsersPresence.test.tsx) so
test names render the online player count correctly.

In `@src/components/elements/GuessGrid/GuessGrid.types.ts`:
- Line 1: The import in GuessGrid.types.ts should use the `import { type ... }`
form; replace the current `import type { CheckedLetter, PuzzleGuessAttempt }`
with `import { type CheckedLetter, type PuzzleGuessAttempt }` so both
CheckedLetter and PuzzleGuessAttempt are explicitly imported as types and follow
project conventions.

In `@src/components/navigation/GenericStackScreen/GenericStackScreen.tsx`:
- Line 2: Replace the type-only import syntax on GenericStackScreen by changing
the import of PropsWithChildren to use the inline type modifier; update the
existing import statement that references PropsWithChildren so it reads with
"import { type PropsWithChildren } from 'react';" (locate the import that
currently says "import type { PropsWithChildren } from 'react';" and adjust it
accordingly).

In `@src/components/ui/Card/Card.tsx`:
- Line 2: The import uses a type-only import statement; update the import to use
inline type specifiers by changing the import of PropsWithChildren and ReactNode
to `import { type PropsWithChildren, type ReactNode } from 'react';` so both
PropsWithChildren and ReactNode are explicitly marked as types in the import
that appears at the top of the Card component file (the existing import line
that currently reads `import type { PropsWithChildren, ReactNode } from
'react';`).

In `@src/components/ui/TextInput/TextInput.tsx`:
- Line 31: Move the ref prop to be the first JSX prop on UniTextInput, then
order the remaining explicit props alphabetically (e.g. accessibilityLabel,
style) and place the {...rest} spread last so explicit props are not
accidentally shadowed; update the UniTextInput element in TextInput.tsx to
follow that ordering.

In `@src/hooks/mutations/generateUseMutationHook.ts`:
- Line 2: The import in generateUseMutationHook.ts uses the `import type {
FunctionReference } from 'convex/server'` form which conflicts with the
project's guideline requiring inline type imports; change the import to the
inline type-only syntax used elsewhere (e.g., `import { type FunctionReference }
from 'convex/server'`) so it matches generateUseQueryHook.ts and the codebase
convention, and verify no other imports in this file use `import type` so the
file is consistent.

In `@src/hooks/queries/generateUseQueryHook.ts`:
- Line 2: The import in generateUseQueryHook.ts uses the `import type {
FunctionReference }` form which conflicts with the project's guideline to use
inline type imports; change the import to the inline type syntax `import { type
FunctionReference } from 'convex/server'` so it matches other files (or, if you
prefer to adopt the `import type` form project-wide, update the Biome/formatter
config and the coding guidelines accordingly); ensure any other occurrences of
`import type { ... }` are adjusted consistently.

In `@src/hooks/useDailyPuzzle/useDailyPuzzle.test.ts`:
- Line 6: Change the type-only import style to match project guidelines: replace
the current import using the "import type { Id }" form with the "import { type
Id } from '@/convex/_generated/dataModel';" style in the test file (referencing
the Id type import at the top of
src/hooks/useDailyPuzzle/useDailyPuzzle.test.ts) so tests use the configured
type-import syntax.

In `@src/hooks/useTrainingPuzzle/useTrainingPuzzle.test.ts`:
- Line 6: Replace the plain type import with the project's type-only import
syntax: change the current import of Id to use the TypeScript type-only form
(import { type Id } ...) so the test module's import of Id uses the configured
"import { type X }" style; update the import statement that references Id in
useTrainingPuzzle.test to use this type-only syntax.

In `@src/hooks/useUser/useUser.ts`:
- Line 6: Update the import to use inline type specifiers to match repo style:
change the import that brings in CreateUser and PatchUser in useUser.ts so it
uses the `type` keyword inline (i.e., import { type CreateUser, type PatchUser }
from '...') instead of `import type { CreateUser, PatchUser }`, ensuring other
code references to CreateUser and PatchUser remain unchanged.

In `@src/utils/notifications.test.ts`:
- Line 93: The test title string in the Jest test starting with "should use the
status received from the requestPermissionsAsyn when status of
getPermissionsAsync is %s" contains a typo; update that string to
"requestPermissionsAsync" (add the missing 'c') so the description reads "should
use the status received from the requestPermissionsAsync when status of
getPermissionsAsync is %s" in the test case that iterates over
getPermissionsAsyncStatus.

In `@src/utils/puzzles.ts`:
- Line 3: Update the import to use TypeScript's type-only import form: replace
the current default-style import of Puzzle with an explicit type import for the
Puzzle symbol from '@/convex/puzzles/models' (i.e., use "import { type Puzzle }
from '@/convex/puzzles/models';") so it follows the project's CLAUDE.md
convention and signals this is a type-only dependency.

---

Nitpick comments:
In `@jest.setup.tsx`:
- Around line 1-2: The imports in jest.setup.tsx use standalone "import type"
syntax; update them to inline type imports to follow repo convention by changing
the two lines importing Octicons and ComponentProps to use "import { type
Octicons } from '@expo/vector-icons'" and "import { type ComponentProps } from
'react'"; ensure only the syntax changes (types remain type-only) and no runtime
imports are altered.

In `@src/__tests__/settings.test.tsx`:
- Line 6: Update the type-only imports to the repo's preferred inline style:
replace the `import type { ComponentProps } from 'react'` form with the `import
{ type ComponentProps } from 'react'` syntax, and do the same for the other
type-only import on line 10 (replace `import type { ... }` with `import { type
... }`) so both ComponentProps and the second imported type use the `import {
type ... }` form.

In `@src/components/ui/RadioInput/RadioInput.tsx`:
- Around line 19-20: The unchecked cast in handleChange (newValue: string) =>
onChange(newValue as Value) should be removed and the context should preserve
the generic Value type so TypeScript can validate item values; update the
RadioInput context type to be generic (e.g., RadioInputContext<Value>) and
change handleChange to accept Value (or narrow/validate the incoming value
before calling onChange) so contextValue is memoized with the correctly typed
handleChange and value, ensuring RadioInput.Item values are type-checked against
the RadioInput<Value> generic rather than bypassed by an any/string cast.

In `@src/components/ui/RadioInput/RadioInput.types.ts`:
- Around line 15-18: The RadioInputContextProps type lost its generic, reducing
type safety; change RadioInputContextProps back to a generic (e.g.,
RadioInputContextProps<Value extends string>) and type it as
Pick<RadioInputProps<Value>, 'value' | 'onChange'> or equivalently { onChange:
(newValue: Value) => void; value?: Value }, then update the RadioInput context
creation and the provider usage in RadioInput.tsx to use the same generic Value
so consumers (like settings.tsx and RadioInput.Item) get compile-time narrowing
and you can remove the unsafe `as Value` cast.

In `@src/context/ActionSheet/ActionSheet.provider.tsx`:
- Line 9: The import uses the non-preferred "import type {
ActionSheetPressCallback }" form; update it to the repo convention by changing
the import to the inline type-import syntax "import { type
ActionSheetPressCallback } from './ActionSheet.types';" so the
ActionSheet.provider.tsx file (and specifically the ActionSheetPressCallback
import) follows the project's type-only import rule.

In `@src/context/Prompt/Prompt.context.ts`:
- Line 3: Replace the type-only import to follow the codebase convention by
changing the import statement that references PromptProviderProps to use the
inline type syntax (import { type PromptProviderProps } ...) instead of import
type { PromptProviderProps }, so update the import that currently names
PromptProviderProps in Prompt.context to the { type ... } form for consistency.

In `@src/hooks/useLeaderboards/useLeaderboards.test.ts`:
- Line 9: Replace the type-only import to match project convention: change the
existing import statement that references Id from "import type { Id } from
'@/convex/_generated/dataModel';" to use the inline type-import style ("import {
type Id } from '@/convex/_generated/dataModel';"), ensuring the symbol Id is
imported with the "type" modifier inside the braces.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8a4d030e-a0d3-432e-94e8-00437d34b60f

📥 Commits

Reviewing files that changed from the base of the PR and between 43ed6d5 and 59a93ee.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (86)
  • .prettierignore
  • .zed/settings.json
  • CLAUDE.md
  • babel.config.cjs
  • biome.json
  • convex/leaderboards/queries.ts
  • convex/migrations.ts
  • convex/shared/queries.ts
  • db/seeders/dictionaryEntries/getDictionaryWords.js
  • db/seeders/dictionaryEntries/getDictionaryWordsExplanations.js
  • eslint.config.js
  • jest.setup.tsx
  • package.json
  • prettier.config.js
  • src/__tests__/index.test.tsx
  • src/__tests__/leaderboards/all-time-leaderboard.test.tsx
  • src/__tests__/leaderboards/weekly-leaderboard.test.tsx
  • src/__tests__/onboard/create-account.test.tsx
  • src/__tests__/onboard/restore-account.test.tsx
  • src/__tests__/play/daily-puzzle-solved.test.tsx
  • src/__tests__/play/training-puzzle-solved.test.tsx
  • src/__tests__/settings.test.tsx
  • src/__tests__/update-nickname.test.tsx
  • src/app/(authenticated)/index.tsx
  • src/app/(authenticated)/leaderboards/weekly-leaderboard.tsx
  • src/app/(authenticated)/play/daily-puzzle-solved.tsx
  • src/app/(authenticated)/play/daily-puzzle.tsx
  • src/app/(authenticated)/play/training-puzzle-solved.tsx
  • src/app/(authenticated)/update-nickname.tsx
  • src/app/_layout.tsx
  • src/app/onboard/create-account.tsx
  • src/app/onboard/restore-account.tsx
  • src/components/elements/DailyPuzzleUsersPresence/DailyPuzzleUsersPresence.test.tsx
  • src/components/elements/DailyPuzzleUsersPresence/DailyPuzzleUsersPresence.tsx
  • src/components/elements/GuessGrid/GuessGrid.helpers.ts
  • src/components/elements/GuessGrid/GuessGrid.hook.ts
  • src/components/elements/GuessGrid/GuessGrid.test.tsx
  • src/components/elements/GuessGrid/GuessGrid.tsx
  • src/components/elements/GuessGrid/GuessGrid.types.ts
  • src/components/elements/HistoryGrid/HistoryGrid.test.tsx
  • src/components/elements/HistoryGrid/HistoryGrid.tsx
  • src/components/elements/Keyboard/Keyboard.test.tsx
  • src/components/elements/Keyboard/Keyboard.tsx
  • src/components/elements/Leaderboard/Leaderboard.tsx
  • src/components/navigation/GenericStackScreen/GenericStackScreen.tsx
  • src/components/ui/Button/Button.tsx
  • src/components/ui/Card/Card.tsx
  • src/components/ui/Hint/Hint.test.tsx
  • src/components/ui/Hint/Hint.tsx
  • src/components/ui/RadioInput/RadioInput.context.ts
  • src/components/ui/RadioInput/RadioInput.test.tsx
  • src/components/ui/RadioInput/RadioInput.tsx
  • src/components/ui/RadioInput/RadioInput.types.ts
  • src/components/ui/Text/Text.tsx
  • src/components/ui/TextInput/TextInput.tsx
  • src/context/ActionSheet/ActionSheet.context.ts
  • src/context/ActionSheet/ActionSheet.provider.tsx
  • src/context/ActionSheet/ActionSheet.test.tsx
  • src/context/ActionSheet/ActionSheet.types.ts
  • src/context/Prompt/Prompt.context.ts
  • src/context/Prompt/Prompt.provider.tsx
  • src/context/Prompt/Prompt.test.tsx
  • src/context/Prompt/Prompt.types.ts
  • src/hooks/mutations/generateUseMutationHook.test.ts
  • src/hooks/mutations/generateUseMutationHook.ts
  • src/hooks/queries/generateUseQueryHook.ts
  • src/hooks/useDailyPuzzle/useDailyPuzzle.test.ts
  • src/hooks/useGameplaySettings/useGameplaySettings.test.ts
  • src/hooks/useLeaderboards/useLeaderboards.test.ts
  • src/hooks/useLeaderboards/useLeaderboards.ts
  • src/hooks/usePlural/usePlural.test.ts
  • src/hooks/usePushNotifications/usePushNotifications.ts
  • src/hooks/usePuzzlesStatistics/usePuzzlesStatistics.test.ts
  • src/hooks/usePuzzlesStatistics/usePuzzlesStatistics.ts
  • src/hooks/useToaster/useToaster.test.ts
  • src/hooks/useTrainingPuzzle/useTrainingPuzzle.test.ts
  • src/hooks/useUser/useUser.ts
  • src/tests/fixtures/leaderboards.ts
  • src/tests/fixtures/puzzleGuessAttempts.ts
  • src/tests/fixtures/puzzleStatistics.ts
  • src/tests/fixtures/puzzles.ts
  • src/tests/fixtures/users.ts
  • src/utils/clone.ts
  • src/utils/notifications.test.ts
  • src/utils/puzzles.ts
  • src/utils/words.ts
💤 Files with no reviewable changes (3)
  • .prettierignore
  • eslint.config.js
  • prettier.config.js

@zigcccc
Copy link
Owner Author

zigcccc commented Mar 19, 2026

@coderabbitai re-review

@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

@zigcccc Sure! I'll kick off a fresh review of the PR right away.


🧠 Learnings used
Learnt from: zigcccc
Repo: zigcccc/petka-app PR: 23
File: .github/workflows/main.yml:194-197
Timestamp: 2025-08-12T11:36:28.340Z
Learning: User zigcccc prefers CI workflows with --no-wait for EAS builds, accepting potential silent failures rather than blocking CI on build completion.

Learnt from: zigcccc
Repo: zigcccc/petka-app PR: 41
File: src/components/elements/GuessGrid/GuessGrid.test.tsx:3-3
Timestamp: 2026-03-19T12:07:42.576Z
Learning: In zigcccc/petka-app (TypeScript/React Native), the preferred type-only import syntax is `import type { X }` (not `import { type X }`). For mixed value+type imports, use `import { Component, type ComponentProps }`. This convention is enforced by Biome (as of PR `#41` migrating from ESLint/Prettier to Biome).

Learnt from: zigcccc
Repo: zigcccc/petka-app PR: 41
File: convex/leaderboards/queries.ts:7-7
Timestamp: 2026-03-19T12:07:51.928Z
Learning: In zigcccc/petka-app, the preferred type-only import syntax has been updated (as of PR `#41` migrating to Biome) from `import { type X }` to `import type { X }`. For mixed imports (value + type in the same statement), use `import { Component, type ComponentProps }` syntax.

Learnt from: zigcccc
Repo: zigcccc/petka-app PR: 41
File: src/tests/fixtures/puzzleGuessAttempts.ts:1-1
Timestamp: 2026-03-19T12:07:36.804Z
Learning: In zigcccc/petka-app, for all **/*.{ts,tsx} files, the preferred type-only import syntax is `import type { X }` (not `import { type X }`). For mixed imports (value + type), use `import { Component, type ComponentProps }` syntax. This was updated in PR `#41` as part of the Biome migration, with the convention documented in CLAUDE.md.

Learnt from: zigcccc
Repo: zigcccc/petka-app PR: 41
File: src/components/elements/GuessGrid/GuessGrid.tsx:7-7
Timestamp: 2026-03-19T12:07:48.694Z
Learning: In zigcccc/petka-app, for **/*.{ts,tsx} files, the project convention for type-only imports is `import type { X }` (top-level type import), not `import { type X }` (inline type specifier). For mixed value+type imports, use `import { Component, type ComponentProps }`. This was updated as part of the Biome migration (PR `#41`).

Learnt from: zigcccc
Repo: zigcccc/petka-app PR: 41
File: src/tests/fixtures/puzzles.ts:1-1
Timestamp: 2026-03-19T12:07:33.674Z
Learning: In zigcccc/petka-app (TypeScript/React Native), the preferred type-only import syntax is `import type { X }` (not `import { type X }`). For mixed imports (value + type), use `import { Component, type ComponentProps }`. This convention was updated in PR `#41` as part of the Biome migration, and is documented in CLAUDE.md.

Learnt from: zigcccc
Repo: zigcccc/petka-app PR: 41
File: convex/leaderboards/queries.ts:1-1
Timestamp: 2026-03-19T12:07:51.869Z
Learning: Applies to **/*.{ts,tsx}: Use `import type { X }` for pure type-only imports. For mixed imports (both values and types), use `import { Component, type ComponentProps }`. This convention was adopted in PR `#41` as part of the migration from ESLint/Prettier to Biome.

Learnt from: CR
Repo: zigcccc/petka-app PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-18T20:43:17.670Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use Prettier formatting: 120-character line width, single quotes, 2-space indent, trailing commas (ES5)
✅ Actions performed

Full review triggered.

@zigcccc zigcccc merged commit 9084b40 into main Mar 19, 2026
4 checks passed
@zigcccc zigcccc deleted the PET-40-replace-eslint-and-prettier-with-biome branch March 19, 2026 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant